// 自上而下预测分析

#include "stdafx.h"
#include "ForseeAnalysis.h"

namespace compile 
{
	// ------------------------------- public -----------------------------------
	ForseeAnalysis::ForseeAnalysis()
	{

	}
	ForseeAnalysis::ForseeAnalysis(string input, ForseeTable* forsee)
	{
		input_stack.push("$");
		for (int i = input.length() - 1; i >= 0; --i)
		{
			input_stack.push(polyfillChar(input[i]));
		}
		word_stack.push((*forsee).getEnter());
		analysisInput(forsee);
	}
	ForseeAnalysis::~ForseeAnalysis()
	{
		UNI word_size = word_stack.size();
		UNI input_size = input_stack.size();

		for (UNI i = 0; i < word_size; ++i)
		{
			word_stack.pop();
		}

		for (UNI i = 0; i < input_size; ++i)
		{
			input_stack.pop();
		}
	}
	// -------------------------------- End public --------------------------------


	// -------------------------------- private ----------------------------------

	void ForseeAnalysis::analysisInput(ForseeTable* forsee)
	{
		while (!word_stack.empty())
		{
			string key = word_stack.top();


			if (!ifEndSign(key[0]))
			{
				pair<string, string> key_pair(key, input_stack.top());
				string search_result = (*forsee).searchTable(key_pair);

				// 没有找到， 以及没有消除左递归，直接退出 
				// PS: 间接左递归没查
				if (search_result.length() == 0 || key == polyfillChar(search_result[0]))
				{
					findError();
				}
				word_stack.pop();
				// 推导进栈
				for (int i = search_result.length() - 1; i >= 0; --i)
				{
					word_stack.push(polyfillChar(search_result[i]));
				}
			}


			// 栈顶为终止符，出栈
			if (word_stack.top() == "$")
			{
				word_stack.pop();
			}

			// 栈顶相等，同时出栈
			if (!word_stack.empty() && word_stack.top() == input_stack.top())
			{
				word_stack.pop();
				input_stack.pop();

			}

			// 当语法栈顶为终结符，而输入栈顶与语法栈顶不匹配时，退出
			if (!word_stack.empty() &&
				ifEndSign(word_stack.top()[0]) &&
				word_stack.top() != "$" &&
				input_stack.top() == "$")
			{
				findError();
			}
		}

		// 未出栈完，错误语法
		if ((input_stack.size() != 0 && input_stack.top() != "$")
			|| input_stack.size() == 0)
		{
			findError();
		}
		cout << "Compiler complete!!!!" << endl;
	}

	// ------------------------------- End private --------------------------------
}